package log

import (
	"fmt"
	"gostore/util"
	"reflect"
	"runtime"
	"time"
)

var currLevel LogLevel = 0

func SetLevel(level LogLevel) {
	if level >= 0 && level < LogLevel(len(types)) {
		currLevel = level
	}
}

type LogLevel int

const (
	DEBUG LogLevel = 0
	INFO  LogLevel = 1
	WARN  LogLevel = 2
	FATAL LogLevel = 3
)

var types = []string{
	"debug", "info", "warn", "fatal",
}

func Debug(args ...interface{}) {
	println(DEBUG, args...)
}

func Info(args ...interface{}) {
	println(INFO, args...)
}

func Warn(args ...interface{}) {
	println(WARN, args...)
}
func Fatal(args ...interface{}) {
	println(FATAL, args...)
}

//format output
func Debugf(format string, args ...interface{}) {
	print(DEBUG, format, args...)
}

func Infof(format string, args ...interface{}) {
	print(INFO, format, args...)
}

func Warnf(format string, args ...interface{}) {
	print(WARN, format, args...)
}
func Fatalf(format string, args ...interface{}) {
	print(FATAL, format, args...)
}

func println(level LogLevel, args ...interface{}) {
	print(level, "%s", fmt.Sprintln(args...))
}

func print(level LogLevel, format string, args ...interface{}) {
	//根据设定的level输出
	if level >= currLevel {
		now := time.Now()
		y, mon, d := now.Date()
		h, min, s := now.Clock()
		datetime := fmt.Sprintf("%d/%d/%d-%d:%d:%d", y, mon, d, h, min, s)
		out := fmt.Sprintf("[%s]%s %s", types[level], datetime, fmt.Sprintf(format, args...))
		//TODO application shuold be exit when log fatal
		if level == FATAL {
			panic(out)
		}
		fmt.Print(out)
		//TODO file output

	}
}

// 带包和方法名的 log
type Logger struct {
	Package string
}

func (log Logger) Debug(args ...interface{}) {
	println(DEBUG, log.Package, fmt.Sprint(args...))
}
func (log Logger) Debugf(format string, args ...interface{}) {
	print(DEBUG, "%s %s", log.Package, fmt.Sprintf(format, args...))
}

func (log Logger) Info(args ...interface{}) {
	println(INFO, log.Package, fmt.Sprint(args...))
}
func (log Logger) Infof(format string, args ...interface{}) {
	print(INFO, "%s %s", log.Package, fmt.Sprintf(format, args...))
}

func (log Logger) Warn(args ...interface{}) {
	println(WARN, log.Package, fmt.Sprint(args...))
}
func (log Logger) Warnf(format string, args ...interface{}) {
	print(WARN, "%s %s", log.Package, fmt.Sprintf(format, args...))
}

func (log Logger) Fatal(args ...interface{}) {
	println(FATAL, log.Package, fmt.Sprint(args...))
}

func (log Logger) Fatalf(format string, args ...interface{}) {
	print(FATAL, "%s %s", log.Package, fmt.Sprintf(format, args...))
}

func Factory(fun interface{}) *Logger {
	pkg := runtime.FuncForPC(reflect.ValueOf(fun).Pointer()).Name()

	pkg = util.Replace(pkg, "gostore/", "")
	return &Logger{
		Package: "[" + pkg + "]",
	}
}
